﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Microsoft.Phone.Applications.Common;
using System.Windows.Threading;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
using System.Windows.Media.Imaging;
using System.IO;
using MemoBoss;
using System.Linq;
using Microsoft.Xna.Framework.Media;
using System.ComponentModel;

namespace Classes
{
    public class Layers : PhoneApplicationPage
    {
        public Layers()
            : this(false)
        {
            transforms = new Dictionary<CurrentView, Dictionary<int, TranslateTransform>>();
            sb = new Dictionary<CurrentView, Storyboard>();
        }
        public Layers(bool manual)
        {
            if (manual) return;

            if (!DesignerProperties.IsInDesignTool)
            {
                if (!App.SettingsInstance.Pseudo3DOnOffSetting) return;
                this.Loaded += new RoutedEventHandler(Layers_Loaded);
            }
        }
        private void Layers_Loaded(object sender, RoutedEventArgs e)
        {
            //if (!App.SettingsInstance.Pseudo3DOnOffSetting) return;
            //initLayers();


        }
        public Duration duration = new Duration(TimeSpan.FromSeconds(0.1));
        public Dictionary<CurrentView, Storyboard> sb;
        public Dictionary<CurrentView, Dictionary<int, DoubleAnimation>> animationsX = new Dictionary<CurrentView, Dictionary<int, DoubleAnimation>>();
        public Dictionary<CurrentView, Dictionary<int, DoubleAnimation>> animationsY = new Dictionary<CurrentView, Dictionary<int, DoubleAnimation>>();
        public void CreateLayerAnimation(int layerIndex, TranslateTransform TT, CurrentView cw)
        {

            // Create a duration of 2 seconds.


            // Create two DoubleAnimations and set their properties.
            DoubleAnimation moveanimX = new DoubleAnimation();
            DoubleAnimation moveanimY = new DoubleAnimation();

            moveanimX.Duration = duration;
            moveanimY.Duration = duration;

            //Storyboard sb = new Storyboard();


            sb[cw].Children.Add(moveanimX);
            sb[cw].Children.Add(moveanimY);

            //TranslateTransform TT = new TranslateTransform();
            Storyboard.SetTarget(moveanimX, TT);
            Storyboard.SetTarget(moveanimY, TT);


            // Set the attached properties of Canvas.Left and Canvas.Top
            // to be the target properties of the two respective DoubleAnimations
            Storyboard.SetTargetProperty(moveanimX, new PropertyPath(TranslateTransform.XProperty));
            Storyboard.SetTargetProperty(moveanimY, new PropertyPath(TranslateTransform.YProperty));

            animationsX[cw].Add(layerIndex, moveanimX);
            animationsY[cw].Add(layerIndex, moveanimY);

            // Make the Storyboard a resource.


            // Add the rectangle to the tree.
            //LayoutRoot.Children.Add(myRectangle

            // Begin the animation.
            //sb.Begin();
        }

        public List<UIElement> GetLayerControls(UIElement root)
        {
            List<UIElement> elts = new List<UIElement>();

            if (((UIElement)root).GetType().GetProperty("Tag") != null &&
                ((UIElement)root).GetType().GetProperty("Tag").GetValue(root, null) != null &&
                typeof(string) == ((UIElement)root).GetType().GetProperty("Tag").GetValue(root, null).GetType() &&
                ((string)(((UIElement)root).GetType().GetProperty("Tag").GetValue(root, null))).Contains("LayerIndex="))
                elts.Add(root);

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
                elts.AddRange(GetLayerControls((UIElement)VisualTreeHelper.GetChild(root, i)));

            return elts;
        }

        public UIElement FindControl(UIElement element, string name)
        {
            if (((UIElement)element).GetType().GetProperty("Name") != null &&
                    ((UIElement)element).GetType().GetProperty("Name").GetValue(element, null) != null &&
                    typeof(string) == ((UIElement)element).GetType().GetProperty("Name").GetValue(element, null).GetType())
            {
                string elName = (string)(((UIElement)element).GetType().GetProperty("Name").GetValue(element, null));
                if (elName == name)
                    return element;
            }
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
            {
                UIElement root = (UIElement)VisualTreeHelper.GetChild(element, i);

                UIElement el = FindControl(root, name);
                if (el != null) return el;

            }
            return null;
        }

        Dictionary<CurrentView, Dictionary<int, TranslateTransform>> transforms;

        public void setLayerAnimations(UIElement LayoutRoot, CurrentView cw)
        {
            if (!transforms.ContainsKey(cw))
                transforms.Add(cw, new Dictionary<int, TranslateTransform>());

            List<UIElement> controls = GetLayerControls(LayoutRoot);

            foreach (UIElement ctl in controls)
            {
                string tag = (string)(((UIElement)ctl).GetType().GetProperty("Tag").GetValue(ctl, null));
                int index;
                if (int.TryParse(tag.Replace("LayerIndex=", ""), out index))
                {
                    if (transforms[cw].ContainsKey(index))
                    {
                        ((UIElement)ctl).GetType().GetProperty("RenderTransform").SetValue(ctl, transforms[cw][index], null);
                    }
                    else
                    {
                        TranslateTransform tt = new TranslateTransform();
                        CreateLayerAnimation(index, tt, cw);
                        transforms[cw].Add(index, tt);
                        ((UIElement)ctl).GetType().GetProperty("RenderTransform").SetValue(ctl, transforms[cw][index], null);
                    }
                }
            }
        }

        //CurrentView currentView;

        Simple3DVector firstread = null;
        Simple3DVector lastread = null;
        public void OnAccelerometerHelperReadingChanged(object sender, AccelerometerHelperReadingEventArgs e)
        {
            if (!App.SettingsInstance.Pseudo3DOnOffSetting)
            {

                StopAccelerometer();
                return;
            }

            Simple3DVector read = e.OptimalyFilteredAcceleration;
            if (firstread == null)
            {
                firstread = read;
                lastread = read;
                return;
            }
            Simple3DVector acc = new Simple3DVector(read.X - firstread.X, read.Y - firstread.Y, read.Z - firstread.Z);

            //e.RawAcceleration.ToString();
            //e.LowPassFilteredAcceleration.ToString();
            //e.OptimalyFilteredAcceleration.ToString();
            //e.AverageAcceleration.ToString();

            // if (previousReading == null) previousReading = acc;
            if (Math.Abs(lastread.X - acc.X) > threshold || Math.Abs(lastread.Y - acc.Y) > threshold)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    sb[App.currentView].Pause();
                    foreach (KeyValuePair<int, TranslateTransform> kvp in transforms[App.currentView])
                    {
                        animationsX[App.currentView][kvp.Key].From = kvp.Value.X;
                        animationsX[App.currentView][kvp.Key].To = acc.X * kvp.Key;
                        animationsY[App.currentView][kvp.Key].From = kvp.Value.Y;
                        animationsY[App.currentView][kvp.Key].To = -acc.Y * kvp.Key;
                    }
                    sb[App.currentView].Begin();
                    sb[CurrentView._background].Pause();
                    foreach (KeyValuePair<int, TranslateTransform> kvp in transforms[CurrentView._background])
                    {
                        animationsX[CurrentView._background][kvp.Key].From = kvp.Value.X;
                        animationsX[CurrentView._background][kvp.Key].To = acc.X * kvp.Key;
                        animationsY[CurrentView._background][kvp.Key].From = kvp.Value.Y;
                        animationsY[CurrentView._background][kvp.Key].To = -acc.Y * kvp.Key;
                    }
                    sb[CurrentView._background].Begin();
                });
                lastread = acc;
            }
        }

        bool AccelerometerStarted = false;
        double threshold = 0.008;
        public void StartAccelerometer()
        {
            if (!AccelerometerStarted)
            {
                if (transforms == null || !transforms.ContainsKey(App.currentView)) return;
                firstread = null;
                foreach (KeyValuePair<int, TranslateTransform> tt in transforms[App.currentView])
                {
                    tt.Value.X = 0;
                    tt.Value.Y = 0;
                }
                if (!transforms.ContainsKey(CurrentView._background)) return;
                foreach (KeyValuePair<int, TranslateTransform> tt in transforms[CurrentView._background])
                {
                    tt.Value.X = 0;
                    tt.Value.Y = 0;
                }

                if (!App.SettingsInstance.Pseudo3DOnOffSetting) return;

                AccelerometerHelper.Instance.Active = true;
                AccelerometerHelper.Instance.ReadingChanged += new EventHandler<AccelerometerHelperReadingEventArgs>(OnAccelerometerHelperReadingChanged);
                AccelerometerStarted = true;
            }
        }
        public void addLayer(UIElement root, CurrentView cw)
        {
            Storyboard stor = new Storyboard();
            sb.Add(cw, stor);
            stor.Duration = duration;
            animationsX.Add(cw, new Dictionary<int, DoubleAnimation>());
            animationsY.Add(cw, new Dictionary<int, DoubleAnimation>());
            this.Resources.Add(string.Format("storyboard{0}", cw.ToString()), stor);
            setLayerAnimations(root, cw);
            //SetBackgroundPicture();
        }

        public void addManualLayerControl(UIElement elem)
        {
            if (sb.ContainsKey(CurrentView._background))
            {
                setLayerAnimations(elem, CurrentView._background);
            }
            else
            {
                Storyboard stor = new Storyboard();
                sb.Add(CurrentView._background, stor);
                stor.Duration = duration;
                animationsX.Add(CurrentView._background, new Dictionary<int, DoubleAnimation>());
                animationsY.Add(CurrentView._background, new Dictionary<int, DoubleAnimation>());
                this.Resources.Add(string.Format("storyboard{0}", CurrentView._background.ToString()), stor);
                setLayerAnimations(elem, CurrentView._background);
            }



            //SetBackgroundPicture();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            StopAccelerometer();
        }
        private void StopAccelerometer()
        {




            if (transforms == null || !transforms.ContainsKey(App.currentView)) return;
            //foreach (KeyValuePair<int, TranslateTransform> tt in transforms[App.currentView])
            //{
            //    Dispatcher.BeginInvoke(() =>
            //    {
            //        tt.Value.X = 0;
            //        tt.Value.Y = 0;
            //    });
            //}
            Dispatcher.BeginInvoke(() =>
                {
                    sb[App.currentView].Pause();
                    foreach (KeyValuePair<int, TranslateTransform> kvp in transforms[App.currentView])
                    {

                        animationsX[App.currentView][kvp.Key].From = kvp.Value.X;
                        animationsX[App.currentView][kvp.Key].To = 0;
                        animationsY[App.currentView][kvp.Key].From = kvp.Value.Y;
                        animationsY[App.currentView][kvp.Key].To = 0;

                    }
                    sb[App.currentView].Begin();
                });
            if (!transforms.ContainsKey(CurrentView._background)) return;
            //foreach (KeyValuePair<int, TranslateTransform> tt in transforms[CurrentView._background])
            //{
            //    Dispatcher.BeginInvoke(() =>
            //    {
            //        tt.Value.X = 0;
            //        tt.Value.Y = 0;
            //    });
            //}
            Dispatcher.BeginInvoke(() =>
               {
                   sb[CurrentView._background].Pause();
                   foreach (KeyValuePair<int, TranslateTransform> kvp in transforms[CurrentView._background])
                   {

                       animationsX[CurrentView._background][kvp.Key].From = kvp.Value.X;
                       animationsX[CurrentView._background][kvp.Key].To = 0;
                       animationsY[CurrentView._background][kvp.Key].From = kvp.Value.Y;
                       animationsY[CurrentView._background][kvp.Key].To = 0;

                   }
                   sb[CurrentView._background].Begin();
               });

            if (AccelerometerStarted)
            {
                AccelerometerHelper.Instance.Active = false;
                AccelerometerHelper.Instance.ReadingChanged -= new EventHandler<AccelerometerHelperReadingEventArgs>(OnAccelerometerHelperReadingChanged);
                AccelerometerStarted = false;
            }
        }
        public void TurnOn()
        {
            if (!App.SettingsInstance.Pseudo3DOnOffSetting) return;

            StartAccelerometer();

        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            TurnOn();

        }
        Image bgImg1;
        Image bgImg2;
        bool? bgImgSwitch;
        Stream picstream;
        Transform tempTransform;
        protected void SetBackgroundPicture_bg()
        {
            try
            {

                bgImg1 = (Image)FindControl(this, "bgImage1");//(Image)this.FindName("bgImage");
                bgImg2 = (Image)FindControl(this, "bgImage2");//(Image)this.FindName("bgImage");
                tempTransform = bgImg1.RenderTransform;
                if (bgImgSwitch == null)
                    bgImgSwitch = true;
                else
                {
                    bgImgSwitch = !bgImgSwitch;
                }

                WriteableBitmap wb = new WriteableBitmap((int)(App.Current.RootVisual as FrameworkElement).ActualWidth + 200, (int)(App.Current.RootVisual as FrameworkElement).ActualHeight + 200);

                //bi.CreateOptions = BitmapCreateOptions.BackgroundCreation;//BitmapCreateOptions.BackgroundCreation;
                //bi.ImageOpened += new EventHandler<RoutedEventArgs>(bmp_ImageOpened);
                //bi.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(bmp_ImageFailed);
                backgroundWorker = new BackgroundWorker();
                backgroundWorker.WorkerSupportsCancellation = true;
                backgroundWorker.DoWork +=
                    (s, e) =>
                    {
                        try
                        {
                            DateTime now = DateTime.Now;
                            Random random = new Random(now.Millisecond);
                            Picture pic;

                            if (App.SettingsInstance.UseAllImagesSetting)
                            {
                                using (var pictures = new Microsoft.Xna.Framework.Media.MediaLibrary().Pictures)
                                {
                                    int num = random.Next(0, pictures.Count - 1);
                                    pic = pictures[num];
                                }
                            }
                            else
                            {
                                int num = random.Next(0, App.collection.PicturesCollection.Count - 1);

                                KeyValuePair<int, int> item = App.collection.PicturesCollection.ElementAt(num);
                                using (var pictures = new Microsoft.Xna.Framework.Media.MediaLibrary().Pictures)
                                {
                                    //pic = pictures.Single(p => p.GetHashCode() == item.Key && p.Name == item.Value);
                                    pic = pictures[item.Value];
                                    if (pic.GetHashCode() != item.Key)
                                    {
                                        pic = pictures.Single(p => p.GetHashCode() == item.Key);
                                    }
                                }
                            }


                            picstream = pic.GetImage();
                            wb.LoadJpeg(picstream);

                            Dispatcher.BeginInvoke(() =>
                            {
                                if (bgImgSwitch.Value)
                                {
                                    bgImg1.Source = wb;
                                    bgImg1.UpdateLayout();
                                    bmp_ImageOpened(bgImg1, null);
                                }
                                else
                                {
                                    bgImg2.Source = wb;
                                    bgImg2.UpdateLayout();
                                    bmp_ImageOpened(bgImg2, null);
                                }

                            });
                        }
                        catch { }
                    };
                backgroundWorker.RunWorkerAsync();
            }
            catch (Exception ex)
            {
            }

        }
        BackgroundWorker backgroundWorker;
        protected void SetBackgroundPicture()
        {
            try
            {


                bgImg1 = (Image)FindControl(this, "bgImage1");//(Image)this.FindName("bgImage");
                bgImg2 = (Image)FindControl(this, "bgImage2");//(Image)this.FindName("bgImage");
                if (App.SettingsInstance.UseAllImagesSetting)
                {
                    using (var pictures = new Microsoft.Xna.Framework.Media.MediaLibrary().Pictures)
                    {
                        if (pictures.Count == 0)
                        {
                            bgImg1.Visibility = System.Windows.Visibility.Collapsed;
                            bgImg2.Visibility = System.Windows.Visibility.Collapsed;
                            return;
                        }
                        else
                        {
                            bgImg1.Visibility = System.Windows.Visibility.Visible;
                            bgImg2.Visibility = System.Windows.Visibility.Visible;
                        }
                    }
                }
                else
                {
                    if (App.collection.PicturesCollection.Count == 0)
                    {
                        bgImg1.Visibility = System.Windows.Visibility.Collapsed;
                        bgImg2.Visibility = System.Windows.Visibility.Collapsed;
                        return;
                    }
                    else
                    {
                        bgImg1.Visibility = System.Windows.Visibility.Visible;
                        bgImg2.Visibility = System.Windows.Visibility.Visible;
                    }
                }

                tempTransform = bgImg1.RenderTransform;
                if (bgImgSwitch == null)
                    bgImgSwitch = true;
                else
                {
                    bgImgSwitch = !bgImgSwitch;
                }

                BitmapImage bi = new BitmapImage();

                bi.CreateOptions = BitmapCreateOptions.BackgroundCreation;//BitmapCreateOptions.BackgroundCreation;
                bi.ImageOpened += new EventHandler<RoutedEventArgs>(bmp_ImageOpened);
                bi.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(bmp_ImageFailed);

                DateTime now = DateTime.Now;
                Random random = new Random(now.Millisecond);
                Picture pic;

                if (App.SettingsInstance.UseAllImagesSetting)
                {
                    using (var pictures = new Microsoft.Xna.Framework.Media.MediaLibrary().Pictures)
                    {
                        int num = random.Next(0, pictures.Count - 1);
                        pic = pictures[num];
                    }
                }
                else
                {

                    int num = random.Next(0, App.collection.PicturesCollection.Count - 1);

                    KeyValuePair<int, int> item = App.collection.PicturesCollection.ElementAt(num);
                    using (var pictures = new Microsoft.Xna.Framework.Media.MediaLibrary().Pictures)
                    {
                        //pic = pictures.Single(p => p.GetHashCode() == item.Key && p.Name == item.Value);
                        pic = pictures[item.Value];
                        if (pic.GetHashCode() != item.Key)
                        {
                            pic = pictures.Single(p => p.GetHashCode() == item.Key);
                        }
                    }
                }

                tmppic = pic;
                picstream = pic.GetImage();
                bi.SetSource(picstream);

                if (bgImgSwitch.Value)
                {
                    bgImg1.Source = bi;
                    bgImg1.UpdateLayout();
                }
                else
                {
                    bgImg2.Source = bi;
                    bgImg2.UpdateLayout();
                }
            }
            catch { }
        }
        Picture tmppic;
        void bmp_ImageOpened(object sender, RoutedEventArgs e)
        {
            picstream.Close();
            picstream.Dispose(); // Debug.WriteLine("opened");
            try
            {
                Duration dur = new Duration(TimeSpan.FromSeconds(1));

                Storyboard bgStoryboard = new Storyboard();

                bgStoryboard.Duration = dur;
                //LayoutRoot.Resources.Add("storyboard", sb);

                DoubleAnimation Opacity1 = new DoubleAnimation();

                Opacity1.Duration = dur;
                DoubleAnimation Opacity2 = new DoubleAnimation();

                Opacity2.Duration = dur;
                //Storyboard sb = new Storyboard();


                bgStoryboard.Children.Add(Opacity1);
                bgStoryboard.Children.Add(Opacity2);

                //TranslateTransform TT = new TranslateTransform();
                if (bgImgSwitch.Value)
                {
                    Storyboard.SetTarget(Opacity1, bgImg1);
                    //Storyboard.SetTarget(moveanimY, TT);
                    Opacity1.From = 0;
                    Opacity1.To = 1;
                    Storyboard.SetTarget(Opacity2, bgImg2);
                    //Storyboard.SetTarget(moveanimY, TT);
                    Opacity2.From = 1;
                    Opacity2.To = 0;
                    //bgImg2.RenderTransform = null;
                    bgImg1.RenderTransform = transforms[CurrentView._background][int.Parse(((string)bgImg1.Tag).Replace("LayerIndex=", ""))];
                }
                else
                {
                    Storyboard.SetTarget(Opacity1, bgImg1);
                    //Storyboard.SetTarget(moveanimY, TT);
                    Opacity1.From = 1;
                    Opacity1.To = 0;
                    Storyboard.SetTarget(Opacity2, bgImg2);
                    //Storyboard.SetTarget(moveanimY, TT);
                    Opacity2.From = 0;
                    Opacity2.To = 1;
                    bgImg2.RenderTransform = transforms[CurrentView._background][int.Parse(((string)bgImg2.Tag).Replace("LayerIndex=", ""))];
                    //bgImg1.RenderTransform = null;
                }

                ObjectAnimationUsingKeyFrames kf = new ObjectAnimationUsingKeyFrames();
                DiscreteObjectKeyFrame dokf = new DiscreteObjectKeyFrame();
                dokf.KeyTime = TimeSpan.FromSeconds(1);
                dokf.Value = null;
                kf.KeyFrames.Add(dokf);

                if (bgImgSwitch.Value)
                {
                    Storyboard.SetTarget(kf, bgImg2);

                }
                else
                {
                    Storyboard.SetTarget(kf, bgImg1);

                }

                bgStoryboard.Children.Add(kf);

                Storyboard.SetTargetProperty(kf, new PropertyPath(Image.RenderTransformProperty));
                // Set the attached properties of Canvas.Left and Canvas.Top
                // to be the target properties of the two respective DoubleAnimations
                Storyboard.SetTargetProperty(Opacity1, new PropertyPath(Image.OpacityProperty));
                Storyboard.SetTargetProperty(Opacity2, new PropertyPath(Image.OpacityProperty));
                bgStoryboard.Completed += new EventHandler(bgStoryboard_Completed);
                bgStoryboard.Begin();
                //animationsX.Add(layerIndex, moveanimX);
                //animationsY.Add(layerIndex, moveanimY);
            }
            catch { }
        }

        void bgStoryboard_Completed(object sender, EventArgs e)
        {
            if (bgImgSwitch.Value)
            {
                bgImg2.RenderTransform = null;
                //bgImg1.RenderTransform = transforms[CurrentView._background][int.Parse(((string)bgImg1.Tag).Replace("LayerIndex=", ""))];
            }
            else
            {
                //bgImg2.RenderTransform = transforms[CurrentView._background][int.Parse(((string)bgImg2.Tag).Replace("LayerIndex=", ""))];
                bgImg1.RenderTransform = null;
            }
        }
        void bmp_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            picstream.Close();
            picstream.Dispose();
            //Debug.WriteLine(e.ErrorException.Message);
        }
    }

}
